import Taro from '@tarojs/taro'

import { tabUrls } from '../config'
import selectOption from '../model/select-option'
import allCitys from './city-list/city-data'
import ApplyFormItem from '../model/apply-form'

import { checkIDCard } from '../utils/idcard-validate';

export class Utils {
  /**
   * 生产一个随机字符串的方法
   * @param n 
   */
  public random = (n) => {
    const chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
    let res = '';
    for (let i = 0; i < n; i++) {
      const id = Math.ceil(Math.random() * 35);
      res += chars[id];
    }
    return res;
  }

  /**
   * 过滤对象中的值为空的key
   * @param obj   对象
   */
  public emptyKeyFilter(obj: any): any {
    const result: any = {}
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        const element = obj[key];
        if (element !== '' && element !== null && element !== undefined) {
          result[key] = element
        }
      }
    }
    return result
  }

  /**
   * 把手机号转换为密码显示，如: 130****5678
   * @param mobile 手机号 例子: 13012345678
   */
  public convertMobileToMaskDisplay(mobile) {
    let result = mobile

    if (mobile) {
      let mobileArr = mobile.split('')
      // 删除中间4位
      mobileArr.splice(3, 4)
      // 插入4个*号
      for (let i = 0; i < 4; i++) {
        mobileArr.splice(3, 0, '*')
      }
      return mobileArr.join('')
    }

    return result
  }

  /**
   * 校验手机号
   * @param {String} phone 手机号
   */
  phoneNumberValidation(phone): boolean {
    // 手机号正则表达式
    const telRegex = /^1[34578]\d{9}$/
    return telRegex.test(phone)
  }

  /**
   * 校验身份证号
   * @param {String} idCard 身份证
   */
  idCardValidation(idCard): boolean {
    return checkIDCard(idCard)
  }

  /**
   * 检查当前url是否tab页面的url
   * @param {string} url
   */
  isTabUrl(url: string): boolean {
    let result = false
    if (typeof url === 'string') {
      for (const item of tabUrls) {
        if (url.includes(item)) {
          result = true
        }
      }
    }
    return result
  }

  /**
   * 根据选项值查询选项对象
   * @param value 选项的value
   * @param options 选项数组
   */
  getOptionName(value: string | number, options: selectOption[] | any[]): selectOption | string | number {
    let result = value
    if (!this.isEmpty(value) && options && options.length > 0) {
      for (let i = 0; i < options.length; i++) {
        if (options[i].value === value) {
          result = options[i].name
          break
        }
      }
    }
    return result
  }

  /**
   * 根据选项下标查询选项对象的值
   * @param index 选项的下标
   * @param options 选项数组
   * @param key 值的key
   */
  getOptionValueByIndex(index: string | number, options: selectOption[] | any[], key?: string): string | number {
    let result = index
    if (options && options.length > 0) {
      const arrIndex = typeof index === 'string' ? parseInt(index) : index
      if (options.length > arrIndex) {
        if (typeof options[arrIndex] === 'object') {
          if (key) {
            result = options[arrIndex][key]
          } else {
            result = options[arrIndex].value
          }
        } else {
          result = options[arrIndex]
        }
      }
    }
    return result
  }

  /**
   * 根据选项值查询选项对象
   * @param index 选项的下标
   * @param options 选项数组
   */
  getOptionNameByIndex(index: string | number, options: selectOption[] | any[]): string | number {
    let result = index
    if (options && options.length > 0) {
      const arrIndex = typeof index === 'string' ? parseInt(index) : index
      if (options.length > arrIndex) {

        if (typeof options[arrIndex] === 'object') {
          result = options[arrIndex].name
        } else {
          result = options[arrIndex]
        }
      }
    }
    return result
  }

  /**
   * 根据选中选项获取该选项在数组中的 index
   * @param value 当前选中选项的值
   * @param options 所有的选项
   * @param key 选项值的key
   */
  getOptionIndex(value: string | number, options: selectOption[] | any[], key?: string): number | string {
    let index = value

    if (!this.isEmpty(value) && options && options.length > 0) {
      for (let i = 0; i < options.length; i++) {
        let curValue = options[i]

        if (key) {
          curValue = curValue[key]
        }

        if (value === curValue || value.toString() === curValue.toString()) {
          index = i
          break
        }
      }
    }
    return index
  }

  /**
   * 根据选中选项获取该选项在数组中的元素
   * @param value 当前选中选项的值
   * @param options 所有的选项
   * @param key 选项值的key
   */
  getOptionByValue(value: string | number, options: selectOption[] | any[], key?: string): selectOption | null {
    let result = null

    if (!this.isEmpty(value) && options && options.length > 0) {
      for (let i = 0; i < options.length; i++) {
        let curValue = options[i]

        if (key) {
          curValue = curValue[key]
        }

        if (value === curValue || value.toString() === curValue.toString()) {
          result = options[i]
          break
        }
      }
    }
    return result
  }

  /**
   * 判断值是否为 '' / undefined / null 的方法
   * @param value 值
   */
  isEmpty(value: any): boolean {
    return value === '' || value === undefined || value === null
  }

  /**
   * 根据id获取省市区列表
   * @param province 省id
   * @param city 市id
   * @param district 区id
   */
  getInitRegionsById(province?: number | string, city?: number | string, district?: number | string) {
    const regions = [[], [], []]

    // 存放省数组
    regions[0] = allCitys.map((item) => {
      return {
        key: item.key,
        name: item.name,
      }
    })

    // 默认选中第一个省
    let selectedProvince = allCitys[0]
    if (province) {
      // 查找选中的省
      for (const provinceItem of allCitys) {
        const { key } = provinceItem
        if (key === province) {
          selectedProvince = provinceItem
          break
        }
      }
    }
    // console.log('selectedProvince = ', selectedProvince)

    // 存放市数组
    regions[1] = selectedProvince['cities']
    // 默认选中第一个市
    let selectedCity = regions[1][0]
    if (city) {
      // 查找选中的市
      for (const cityItem of regions[1]) {
        const { key } = cityItem
        if (key === city) {
          selectedCity = cityItem
          break
        }
      }
    }

    // 存放区数组
    regions[2] = selectedCity['regions']

    return regions
  }

  /**
   * 表单校验方法
   * 根据传入的表单对象对表单值进行校验
   * @param form form表单的定义数组
   * @param formValue form表单的值
   */
  formValidation(form: ApplyFormItem[], formValue: any): {
    isValidate: boolean,
    msg: string
  } {
    let result = {
      isValidate: true,
      msg: ''
    }

    if (form.length > 0) {
      for (const item of form) {
        const { name, label, isRequire, validator } = item
        const formItemValue = formValue[name]
        if (isRequire) {
          if (formItemValue === null || formItemValue === undefined || formItemValue === '' || (Array.isArray(formItemValue) && formItemValue.length === 0) ) {
            result.isValidate = false
            result.msg = `请填写${label}`

            break
          }

          if (Array.isArray(validator)) {
            for (const validateFunc of validator) {
              // 调用验证方法
              const validationResult = validateFunc.call(null, formItemValue)

              if (validationResult && !validationResult.isValidate) {
                result = validationResult
                break
              }
            }
          }
        }
      }
    }
    return result
  }

  /**
  * 把订单号转换为日期
  * @param orderNum 订单号， 例子: 1811291318
  */
  convertOrderNumToDate(orderNum: string): string {
    let result = orderNum.toString()
    const year = orderNum.slice(0, 2)
    const month = orderNum.slice(2, 4)
    const day = orderNum.slice(4, 6)
    result = '20' + year + '.' + month + '.' + day
    return result
  }

  /**
   * 把字符串中所有 换行符(\n) 转换为字符串
   * @param text 字符串
   */
  format(text): string {
    if (!text) {
      return ''
    }
    const reg = new RegExp('\n', 'g')
    return text.replace(reg, '\n')
  }

  showLoadingCenter(title?: string) {
    // 使用小程序的loading效果
    Taro.showLoading({
      title: title || '加载中',
      mask: true,
    })
  }

  hideLoadingCenter() {
    Taro.hideLoading()
  }

  /**
   * 根据查询参数拼接url
   * @param url url字符串
   * @param param 查询参数
   */
  getUrlWithParam(url: string, param: any): string {
    let result = url
    
    let i = 0
    for (const key in param) {
      if (param.hasOwnProperty(key)) {
        const value = param[key]

        if (!this.isEmpty(value)) {
          if (i === 0) {
            result = `${result}?${key}=${value}`
          } else {
            result = `${result}&${key}=${value}`
          }
          i++
        }
      }
    }
    return result
  }

}